﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Windows.Forms;
using Moonlite.Compiling;
using Moonlite.Data.Mpq;
using Moonlite.ExtensionApi.ControlInterfaces;
using Moonlite.ExtensionApi.GlobalInterfaces;
using Moonlite.Platform.General;
using Moonlite.Platform.Project;

namespace Moonlite.UI.Shell.Controls
{
    public class NativeNode : TreeNode
    {
        public const int TypeImageIndex = 10;
        private IProject project;
        private Hashtable createdFolders = new Hashtable();

        private int GetImageIndex(string extension)
        {
            extension = extension.IndexOf(".") > -1 ? extension.Substring(extension.IndexOf(".") + 1) : extension;
            foreach (string key in Global.ProjectManagerAvailableFileExtensions.Keys)
            {
                if (key == extension) return Global.ProjectManagerAvailableFileExtensions[key];
            }

            return Global.FileGenericImageIndex;
        }

        private void AddMapNativeData(string mapFilePath)
        {
            if (File.Exists(mapFilePath))
            {
                using (TMPQArchive archive = new TMPQArchive(mapFilePath))
                {
                    Nodes.Clear();
                    foreach (TMPQFileInfo file in archive.GetFiles())
                    {
                        TreeNode folderNode = null;
                        string dummyFilePath = file.FileName;
                        if (dummyFilePath.Contains("\\"))
                        {
                            dummyFilePath = dummyFilePath.Substring(0, dummyFilePath.LastIndexOf("\\") + "\\".Length);
                        }

                        if (createdFolders.ContainsKey(dummyFilePath))
                        {
                            folderNode = (TreeNode)createdFolders[dummyFilePath];
                        }
                        else
                        {
                            TreeNode current = this;
                            while (dummyFilePath.Contains("\\"))
                            {
                                string name = dummyFilePath.Substring(0, dummyFilePath.IndexOf("\\"));
                                dummyFilePath = dummyFilePath.Substring(dummyFilePath.IndexOf("\\") + "\\".Length);
                                if (createdFolders.ContainsKey(dummyFilePath))
                                {
                                    current = (TreeNode)createdFolders[dummyFilePath];
                                }

                                TreeNode folder = new TreeNode(name, 0, 0);
                                folder.Tag = new ProjectFolder() { Name = name, Parent = (IProjectFolder)current.Tag, ReadOnly = true };
                                current.Nodes.Add(folder);
                                string folderPath = name;
                                TreeNode currentFolder = folder;
                                while (true)
                                {
                                    currentFolder = currentFolder.Parent;
                                    if (currentFolder == null || !(currentFolder.Tag is IProjectFolder))
                                    {
                                        break;
                                    }
                                    else
                                    {
                                        folderPath = currentFolder.Text + "\\" + folderPath;
                                    }
                                }

                                createdFolders.Add(folderPath + (!folderPath.EndsWith("\\") ? "\\" : ""), folder);
                                current = folder;
                            }

                            folderNode = current;
                        }

                        TreeNode node = new TreeNode(file.FileName);
                        int imageIndex = GetImageIndex(Path.GetExtension(file.FileName));
                        node.ImageIndex = imageIndex;
                        node.SelectedImageIndex = imageIndex;
                        node.Tag = file.FileName;
                        if (folderNode == null)
                        {
                            Nodes.Add(node);
                        }
                        else
                        {
                            node.Text = node.Text.IndexOf("\\") > -1 ? node.Text.Substring(node.Text.LastIndexOf("\\") + "\\".Length) : node.Text;
                            folderNode.Nodes.Add(node);
                        }
                    }
                }
            }
        }

        internal void ItemOpen(object sender, ItemOpenEventArgs e)
        {
            string filename = e.Node.Tag as string;
            if (filename != null)
            {
                string mapPath = project.GetMapPath();
                try
                {
                    string tempFileName = Path.GetTempFileName();
                    File.Delete(tempFileName);
                    string targetFilePath = Path.GetDirectoryName(tempFileName) + "\\" + Path.GetFileNameWithoutExtension(tempFileName) + Path.GetExtension(filename);
                    if (File.Exists(targetFilePath))
                    {
                        File.Delete(targetFilePath);
                    }

                    using (TMPQArchive archive = new TMPQArchive(mapPath))
                    {
                        archive.ExportFile(filename, targetFilePath);
                    }

                    if (!File.Exists(targetFilePath))
                    {
                        throw new Exception(string.Format("Unable to export file '{0}' from Mpq archive '{1}'.", filename, mapPath));
                    }
                    else
                    {
                        IProjectFile file = new ProjectFile() { Name = Path.GetFileName(targetFilePath), Path = targetFilePath, ReadOnly = true };
                        if (ProjectManager.AssociatedActions.ContainsKey(Path.GetExtension(file.Path)))
                        {
                            foreach (ProjectManagerOpenFileAction action in ((List<ProjectManagerOpenFileAction>)(ProjectManager.AssociatedActions[Path.GetExtension(file.Path)])))
                            {
                                action.Invoke(file, e.Node);
                            }
                        }
                        else
                        {
                            Global.Instance.OpenFile(targetFilePath, new ProjectFile() { Name = Path.GetFileName(targetFilePath), Path = targetFilePath, ReadOnly = true });
                        }
                    }
                }
                catch (Exception exception)
                {
                    MessageBox.Show("An error occured while opening file embedded in the current project's Mpq." + Environment.NewLine + exception.Message);
                }
            }
        }

        public NativeNode(IProject project)
            : base("Native", TypeImageIndex, TypeImageIndex)
        {
            string mapFilePath = project.GetMapPath();
            this.project = project;
            AddMapNativeData(mapFilePath);
            CompilerManager.Compiled += (object sender, EventArgs e) =>
            {
                try
                {
                    if (File.Exists(mapFilePath))
                    {
                        AddMapNativeData(mapFilePath);
                    }
                }
                catch
                {
                }
            };
        }
    }
}
